package service

import (
	"awesomeProject/app/model"
	"awesomeProject/app/request"
	"awesomeProject/app/response"
	"awesomeProject/global"
	"awesomeProject/util"
	"context"
	"encoding/json"
	"fmt"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo"
	"regexp"
	"strconv"
	"strings"
	"time"
)

type ShopStatisticsSrv struct{}

func (s ShopStatisticsSrv) Summary(req request.ShopStatisticsPagination, shopIds []uint) response.Resp {
	offset := (req.PageIndex - 1) * req.PageSize
	var resp map[string]interface{}
	where := "status=1"
	if req.ShopId != 0 {
		where += fmt.Sprintf(" and shop_id=%d", req.ShopId)
	} else {
		if len(shopIds) > 0 {
			b, _ := json.Marshal(shopIds)
			var shopIdStr = string(b)
			shopIdStr = strings.Trim(shopIdStr, "[]")
			where += fmt.Sprintf(" and `shop_id` in (%s)", shopIdStr)
		}
	}

	var total int64
	err := global.Gorm.Model(&model.Account{}).Where(where).Count(&total).Error
	if err != nil {
		return response.ErrQuery
	}
	if total == 0 {
		return response.OK.WithData(resp)
	}
	var accounts []model.Account
	err = global.Gorm.Where(where).Offset(offset).Limit(req.PageSize).Find(&accounts).Error
	if err != nil {
		return response.ErrQuery
	}
	if len(accounts) == 0 {
		response.OK.WithData(map[string]interface{}{
			"total": total,
			"list":  nil,
		})
	}

	shopIds = []uint{}
	for _, account := range accounts {
		shopIds = append(shopIds, account.ShopId)
	}

	// 组织信息
	var companies []model.Company
	err = global.Gorm.Find(&companies).Error
	if err != nil {
		return response.ErrQuery
	}
	companyDict := make(map[uint]model.Company)
	for _, company := range companies {
		companyDict[company.ID] = company
	}

	// 统计信息
	cursor, err := global.MongoDB.Collection("merchant_count").Find(
		context.Background(),
		bson.M{},
	)
	if err != nil {
		return response.ErrQuery.SetMsg(err.Error())
	}
	var merchantCount []model.MerchantCount
	if err = cursor.All(context.TODO(), &merchantCount); err != nil {
		return response.ErrQuery.SetMsg(err.Error())
	}
	msDict := make(map[uint]model.MerchantCount)
	for _, mc := range merchantCount {
		msDict[mc.ShopId] = mc
	}

	// dsr
	//cursor, err = global.MongoDB.Collection("dsr").Find(
	//	context.Background(),
	//	bson.E{Key: "shopId", Value: bson.M{"$in": shopIds}},
	//)
	//if err != nil {
	//	return response.ErrQuery.SetMsg(err.Error())
	//}
	//var dsr []model.Dsr
	//fmt.Println(bson.M{"shopId": bson.M{"$in": shopIds}})
	//if err = cursor.All(context.TODO(), &dsr); err != nil {
	//	return response.ErrQuery.SetMsg(err.Error())
	//}
	//dsrDict := make(map[uint]model.Dsr)
	//for _, d := range dsr {
	//	dsrDict[uint(d.ShopId)] = d
	//}

	// orderStatusCount
	currentTime, _ := time.ParseInLocation("2006-01-02", time.Now().Format("2006-01-02"), time.Local)
	preTime := currentTime.Unix() + 3600 - 7*24*3600
	orderFilter := bson.D{}
	orderFilter = append(orderFilter, bson.E{Key: "shop_id", Value: bson.M{"$in": shopIds}})
	orderFilter = append(orderFilter, bson.E{Key: "skus.cancelMark", Value: 1})
	orderFilter = append(orderFilter, bson.E{Key: "status", Value: 99})
	orderFilter = append(orderFilter, bson.E{Key: "paymentAt", Value: bson.M{"$gte": preTime * 1000}})
	match := bson.D{{"$match", orderFilter}}
	group := bson.D{{
		"$group", bson.D{
			{"_id", bson.D{
				{"shop_id", bson.M{"$toInt": "$shop_id"}},
				{"status", bson.M{"$toInt": "$status"}},
			}},
			{"lack_cancel_count", bson.M{"$sum": 1}},
		},
	}}
	cursor, err = global.MongoDB.Collection("orders").Aggregate(context.TODO(), mongo.Pipeline{match, group})
	if err != nil {
		return response.ErrQuery.SetMsg(err.Error())
	}
	var result []model.OrderStatusCountForSummary
	if err = cursor.All(context.TODO(), &result); err != nil {
		return response.ErrQuery.SetMsg(err.Error())
	}
	orderDict := make(map[uint]model.OrderStatusCountForSummary)
	for _, o := range result {
		orderDict[uint(o.ID.ShopId)] = o
	}

	// 切实库
	now := time.Now() // 获取当前时间
	timestamp := now.AddDate(0, 0, -7).Unix()
	wareHorseFilter := bson.D{
		bson.E{Key: "shopId", Value: bson.M{"$in": shopIds}},
		bson.E{Key: "title", Value: "高缺货ODR店铺管控"},
		bson.E{Key: "receivedTime", Value: bson.M{"$gte": timestamp}},
	}
	cursor, err = global.MongoDB.Collection("official_message").Aggregate(
		context.Background(),
		mongo.Pipeline{
			bson.D{{"$match", wareHorseFilter}},
			bson.D{{"$sort", bson.M{"receivedTime": 1}}},
			bson.D{{
				"$group", bson.D{
					{"_id", bson.M{"$toInt": "$shopId"}},
					{"last_msg", bson.M{"$last": "$$ROOT"}},
				},
			}},
		},
	)
	if err != nil {
		return response.ErrQuery.SetMsg(err.Error())
	}
	var messages []model.GroupOfficialMessage
	if err = cursor.All(context.TODO(), &messages); err != nil {
		return response.ErrQuery.SetMsg(err.Error())
	}
	re := regexp.MustCompile("全店已切为实库销售") // 匹配规则
	messagesDict := make(map[uint]model.OfficialMessage)
	for _, m := range messages {
		msg := m.LastMsg
		if len(re.FindAllString(msg.Content, -1)) == 0 {
			msg.TransMark = "否"
		} else {
			msg.TransMark = "是"
			receivedTime := util.GetInterfaceToInt(msg.ReceivedTime)
			msg.LastTransAt = util.UnixToStr(int64(receivedTime), "2006-01-02 15:04:05")
			re = regexp.MustCompile("近60天受限已达(.*?)次") // 匹配规则
			matchArr := re.FindStringSubmatch(msg.Content)
			if len(matchArr) == 0 {
				msg.TransTimes = "0"
			} else {
				transTimes := matchArr[len(matchArr)-1]
				msg.TransTimes = transTimes
			}
		}
		messagesDict[msg.ShopId] = msg
	}
	// 评价
	shopDataFilter := bson.D{
		bson.E{Key: "shop_id", Value: bson.M{"$in": shopIds}},
	}
	cursor, err = global.MongoDB.Collection("shop_data").Find(context.Background(), shopDataFilter)
	if err != nil {
		return response.ErrQuery.SetMsg(err.Error())
	}
	var shopData []model.ShopData
	if err = cursor.All(context.TODO(), &shopData); err != nil {
		return response.ErrQuery.SetMsg(err.Error())
	}
	re = regexp.MustCompile("近180天差评数(\\d+),评论数(\\d+)") // 匹配规则
	shopDataDict := make(map[uint]model.ShopData)
	for _, sd := range shopData {
		desc := strings.Replace(sd.ShopScore[0].Desc, " ", "", -1)
		matchArr := re.FindStringSubmatch(desc)
		if len(matchArr) > 0 {
			sd.ShopScore[0].CommentSum, _ = strconv.Atoi(matchArr[2])
			sd.ShopScore[0].BadCommentSum, _ = strconv.Atoi(matchArr[1])
		}
		shopDataDict[uint(sd.ShopId)] = sd
	}
	// 周期售后
	afterSaleFilter := bson.D{bson.E{Key: "shopId", Value: bson.M{"$in": shopIds}}}
	today := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.Local)
	lastFifteenDate := time.Date(now.Year(), now.Month(), now.Day()-15, 0, 0, 0, 0, time.Local)
	lastThirtyDate := time.Date(now.Year(), now.Month(), now.Day()-30, 0, 0, 0, 0, time.Local)
	preFilter := append(afterSaleFilter, bson.E{
		Key: "createdAt",
		Value: bson.M{
			"$gte": lastThirtyDate.Unix() * 1000,
			"$lte": today.Unix() * 1000,
		},
	})
	nextFilter := append(afterSaleFilter, bson.E{
		Key: "createdAt",
		Value: bson.M{
			"$gte": lastFifteenDate.Unix() * 1000,
			"$lte": today.Unix() * 1000,
		},
	})
	preMatch := bson.D{{"$match", preFilter}}
	currentMatch := bson.D{{"$match", nextFilter}}
	group = bson.D{{
		"$group", bson.D{
			{"_id", "$shopId"},
			{"count", bson.M{"$sum": 1}},
		},
	}}
	pTotal, err := global.MongoDB.Collection("refund_order").Aggregate(context.TODO(), mongo.Pipeline{preMatch, group})
	if err != nil {
		return response.ErrQuery.SetMsg(err.Error())
	}
	type AfterSaleCount struct {
		ID    uint `json:"_id" bson:"_id"`
		Count uint `json:"count" bson:"count"`
	}
	var pResult []AfterSaleCount
	if err = pTotal.All(context.TODO(), &pResult); err != nil {
		return response.ErrQuery.SetMsg(err.Error())
	}
	pResultDict := make(map[uint]AfterSaleCount)
	for _, pres := range pResult {
		pResultDict[pres.ID] = pres
	}

	nTotal, err := global.MongoDB.Collection("refund_order").Aggregate(context.TODO(), mongo.Pipeline{currentMatch, group})
	if err != nil {
		return response.ErrQuery.SetMsg(err.Error())
	}
	var cResult []AfterSaleCount
	if err = nTotal.All(context.TODO(), &cResult); err != nil {
		return response.ErrQuery.SetMsg(err.Error())
	}
	cResultDict := make(map[uint]AfterSaleCount)
	for _, cres := range cResult {
		cResultDict[cres.ID] = cres
	}

	// 组装数据
	//for _, shop := range shops {
	//	shopsDict[shop.ShopId] = shop
	//}
	var respData []model.ShopStatisticsOld
	for _, account := range accounts {
		var respItem model.ShopStatisticsOld
		if value, ok := companyDict[account.CompanyId]; ok {
			account.CompanyName = value.CompanyName
		}
		respItem.Account = account
		if value, ok := msDict[account.ShopId]; ok {
			respItem.MerchantCount = value
		}
		//if value, ok := dsrDict[account.ShopId]; ok {
		//	respItem.Dsr = value
		//}
		if value, ok := orderDict[account.ShopId]; ok {
			respItem.OrderStatusCountForSummary = value
		}
		if value, ok := messagesDict[account.ShopId]; ok {
			respItem.OfficialMessage = value
		} else {
			respItem.OfficialMessage = model.OfficialMessage{
				TransMark:   "否",
				LastTransAt: "--",
				TransTimes:  "0",
			}
		}
		if value, ok := shopDataDict[account.ShopId]; ok {
			respItem.ShopData = value
		}
		if value, ok := pResultDict[account.ShopId]; ok {
			respItem.AfterSalePre = int(value.Count)
		}
		if value, ok := cResultDict[account.ShopId]; ok {
			respItem.AfterSaleCurrent = int(value.Count)
		}
		respData = append(respData, respItem)
	}

	return response.OK.WithData(map[string]interface{}{
		"total": total,
		"list":  respData,
	})
}

func (s ShopStatisticsSrv) SummaryNew(req request.ShopStatisticsPagination, shopIds []uint) response.Resp {
	offset := (req.PageIndex - 1) * req.PageSize
	var resp map[string]interface{}
	where := "accounts.status=1 and accounts.shop_id<>0"
	if req.ShopId != 0 {
		where += fmt.Sprintf(" and accounts.shop_id=%d", req.ShopId)
	} else {
		if len(shopIds) > 0 {
			b, _ := json.Marshal(shopIds)
			var shopIdStr = string(b)
			shopIdStr = strings.Trim(shopIdStr, "[]")
			where += fmt.Sprintf(" and accounts.`shop_id` in (%s)", shopIdStr)
		}
	}
	if req.CompanyId != 0 {
		where += fmt.Sprintf(" and accounts.company_id=%d", req.CompanyId)
	}
	sort := ""
	if req.Sort != "" {
		sort = strings.Replace(req.Sort, "@", " ", -1)
		fmt.Println(sort)
	}
	if req.LimitFlag != 0 {
		if req.LimitFlag-1 == 0 {
			where += " and (" + fmt.Sprintf("`ShopStatistics`.limit_flag=%d", req.LimitFlag-1) + " or `ShopStatistics`.limit_flag is null)"
		} else {
			where += fmt.Sprintf(" and `ShopStatistics`.limit_flag=%d", req.LimitFlag-1)
		}
	}
	//global.LoggerOut(where)
	var total int64
	err := global.Gorm.Model(&model.Account{}).Where(where).Joins("LEFT JOIN `shop_statistics` `ShopStatistics` ON `accounts`.`shop_id` = `ShopStatistics`.`shop_id`").Count(&total).Error
	if err != nil {
		return response.ErrQuery
	}
	if total == 0 {
		return response.OK.WithData(resp)
	}

	var shopStatistics []model.AccountShopStatistics
	//global.LoggerOut(where)
	err = global.Gorm.Where(where).Joins("ShopStatistics").Joins("ShopStatisticsYesterday").
		Order(sort).
		Offset(offset).Limit(req.PageSize).Find(&shopStatistics).Error
	if err != nil {
		return response.ErrQuery
	}

	// 组织信息
	var companies []model.Company
	err = global.Gorm.Find(&companies).Error
	if err != nil {
		return response.ErrQuery
	}
	companyDict := make(map[uint]model.Company)
	for _, company := range companies {
		companyDict[company.ID] = company
	}

	for i, ss := range shopStatistics {
		shopStatistics[i].CompanyName = companyDict[ss.CompanyId].CompanyName
	}
	return response.OK.WithData(map[string]interface{}{
		"total": total,
		"list":  shopStatistics,
	})

}

func (s ShopStatisticsSrv) Single(req request.ShopStatistics) response.Resp {
	where := fmt.Sprintf("shop_id=%d", req.ShopId)

	var shopStatistics model.AccountShopStatistics
	err := global.Gorm.Where(where).Preload("ShopStatistics").First(&shopStatistics).Error
	if err != nil {
		return response.ErrQuery
	}

	return response.OK.WithData(shopStatistics)

}

func (s ShopStatisticsSrv) Sale(req request.ShopStatisticsPagination, shopIds []uint) response.Resp {
	offset := (req.PageIndex - 1) * req.PageSize
	where := "`accounts`.status=1 and accounts.shop_id<>0"
	if req.ShopId != 0 {
		where += fmt.Sprintf(" and accounts.shop_id=%d", req.ShopId)
	} else {
		if len(shopIds) > 0 {
			b, _ := json.Marshal(shopIds)
			var shopIdStr = string(b)
			shopIdStr = strings.Trim(shopIdStr, "[]")
			where += fmt.Sprintf(" and accounts.`shop_id` in (%s)", shopIdStr)
		}
	}
	if req.CompanyId != 0 {
		where += fmt.Sprintf(" and `accounts`.company_id=%d", req.CompanyId)
	}
	var total int64
	err := global.Gorm.Model(&model.Account{}).Where(where).Count(&total).Error
	if err != nil {
		return response.ErrQuery
	}
	if total == 0 {
		return response.OK.WithData(map[string]interface{}{})
	}

	sort := ""
	if req.Sort != "" {
		sort = strings.Replace(req.Sort, "@", " ", -1)
		fmt.Println(sort)
	}
	var shopSaleStatistics []model.AccountShopSaleStatistics
	err = global.Gorm.Where(where).Joins("ShopSaleStatistics").
		Order(sort).
		Offset(offset).Limit(req.PageSize).Find(&shopSaleStatistics).Error
	if err != nil {
		return response.ErrQuery
	}

	return response.OK.WithData(map[string]interface{}{
		"total": total,
		"list":  shopSaleStatistics,
	})
}

func (s ShopStatisticsSrv) ItemSale(req request.ShopItemSaleStatistics) response.Resp {
	where := fmt.Sprintf("shop_id=%d", req.ShopId)
	var shopItemSaleStatistics []model.ShopItemSaleStatistics
	err := global.Gorm.Where(where).
		Order("grand_total desc").Limit(10).Find(&shopItemSaleStatistics).Error
	if err != nil {
		return response.ErrQuery
	}

	return response.OK.WithData(shopItemSaleStatistics)
}
